function defineReactive(data, key, value) {
  Object.defineProperty(data, key, {
    // writable: false, // 属性是否能够修改
    enumerable: true, // 属性是否可以枚举，即是否允许遍历
    configurable: true, // 属性是否可以删除或编辑
    get: function () {
      console.log(`get key: ${key}, value: ${value}`);
      return value;
    },
    set: function (newValue) {
      console.log(`set key: ${key}, value: ${newValue}`);
      value = newValue;
    },
  });
}

function observe(data) {
  Object.keys(data).forEach(function (key) {
    defineReactive(data, key, data[key]);
  });
}

let o = {
  a: 1,
};
observe(o);
console.log(o.a); // 触发get
o.a = 2; // 触发set
o.b = 1; // 监听不到变化

let arr = ['yd', 2, 3];
observe(arr);

arr[1] = 4; // 触发set
arr[2] = 5; // 触发set

arr[4] = 'asd'; // 监听不到变化

// 头部添加元素，会多次触发defineProperty的set get方法 ，这就是vue为什么重写数组的原因
// 为什么会触发多次：因为头部添加会造成索引后移，对应的key都发生了变化
arr.unshift(0); // 触发多次set get

// defineProperty 可以监听数组的变化（新增加的元素监听不到）
// 注意：defineProperty监听的是 初始化的过程中，就需要去监听对象or数组对应key
// 在对象or数组 中途添加的key是监听不到的
